上次講到了Strong Parameters,今天我們就從Flash開始吧!
在按下按鈕後,應該要有個訊息出現告知使用者是否有成功或失敗,並且只出現一次,這就是快閃訊息做的事。
在這個專案,我們希望如果 create 成功,會將網頁導向 首頁 並印出 "新增候選人成功!!",反之若失敗,則印出”新增候選人失敗!!” (一樣false還沒寫入)
#上略
def create
clean_params = params.require(:candidate).permit(:name, :age, :policy, :party)
@candidate = Candidate.new(clean_params)
if @candidate.save
flash[:notice] = "新增候選人成功!!" #第7~8行可直接寫成 redirect_to root_path, notice: "新增候選人成功!!"
redirect_to root_path
else
flash[:notice] = "新增候選人失敗!!" #第10~11行可直接寫成 redirect_to root_path, notice: "新增候選人失敗!!"
redirect_to root_path
end
end
end
#並在index.html.erb檔加入
<%= flash[:notice] %> 印出"新增候選人成功!"
想要在首頁做事情,那當然是去 index
做事,首先針對 candidate_controller.rb 裡的 index method寫入:
@candidates = Candidate.all
注意:這裡的實體變數故意列為"複數",因為是撈出全部候選人的資料
去抓所有使用者輸入的資料。
再來到 index.html.erb
利用each迴圈印出所有候選人的"姓名"。
<%= flash[:notice] %>
<h1>首頁:候選人列表</h1>
# <%%>不顯示在頁面
#<=%%>要顯示在頁面上
<ul>
<% @candidates.each do |candidate| %> #注意是@candidate"s"
<li><%= candidate.name %></li>
<% end %>
</ul>
<%= link_to '新增候選人', new_candidate_path, class: 'btn btn-danger btn-lg' %>
人打字總偶爾有肥手指、眼睛業障或看錯欄位的狀況發生,所以每個輸入的資料都需要做進一步的認證才能進入資料庫。
(總不可能候選人只有3歲吧!!!?)
還記得剛剛寫的 if else
判斷總是忽略 false
的話怎麼辦對吧? 如果不寫入以下程式碼的話,永遠不會進入到 else
的判斷,到 candidate.rb 裡新增:
class Candidate < ApplicationRecord
validates :name, presence: true
#腦補眼鏡
#validates (:name, {presence: true})
validates :age, numericality: { greater_than_or_equal_to: 40 }
#腦補眼鏡
#validates (:age, {numericality: { {greater_than_or_equal_to: 40} }})
end
姓名欄位: 有資料才會會回傳true ; 年紀欄位: 必須大於或等於40歲
其實我們再 create
中的 if else
判斷式寫的較不人性化,若今天使用者打錯某字跳出"新增候選人失敗!!",回到新增頁面後竟然還要重新打字,是不是太麻煩了? 所以我們要修正else
後的輸出方式:
class CandidatesController < ApplicationController
def index
@candidate = Candidate.all
end
def new
@candidate = Candidate.new
end
def create
clean_params = params.require(:candidate).permit(:name, :age, :policy, :party)
@candidate = Candidate.new(clean_params)
if @candidate.save
flash[:notice] = "新增候選人成功!"
redirect_to root_path
else
#原來寫法:flash[:notice] = "新增候選人失敗!"
#原來寫法:redirect_to root_path
render :new # 借new.html.erb這個檔案,並不是上方的new方法!!!
end
end
end
就解決了如果打錯字回到頁面後文字被洗掉的問題。
若輸入錯誤的話,總要告訴使用者是哪裡輸入錯誤吧?
new.html.erb內新增判斷式,就會印出Rails內建的full_messages
資料庫訊息:
<h1>新增候選人</h1>
<% if @candidate.errors.any? %> #.errors.any? =>有錯誤嗎?
<ul>
<% @candidate.errors.full_messages.each do |message| %> # .full_messages => Rails內建的錯誤訊息資料庫
<li><%= message %></li>
<% end %>
</ul>
<% end %>
<%= form_for(@candidate) do |form| %>
#下略....
當然在看候選人的時候不可能只看名字吧?所以我們要做一個只要點選候選人姓名,就轉至候選人資料的頁面。
index.html.erb頁面:
#index.html.erb
<%= flash[:notice] %>
<h1>首頁:候選人列表</h1>
<!--
<ul>
<% @candidate.each do |candidate| %>
<li><%= candidate.name %></li>
<% end %>
</ul> -->
<ul>
<% @candidate.each do |candidate| %>
<!--路徑需查 rails routes -->
<li><%= link_to candidate.name, candidate_path(candidate.id) %></li>
<% end %>
</ul>
<%= link_to '新增候選人', new_candidate_path, class: 'btn btn-danger btn-lg' %>
就會是可以點選的狀態了,能夠預期若按下候選人姓名會發生什麼事嗎?
因為我們還沒有建立在 show 方法:
def show
@candidate = Candidate.find_by(id: params[:id])
#Candidate.find_by => Rails內建尋找相對應資料的方法
#腦補眼鏡({id: params[:id]})
end
({id: params[:id]}) :取params
內key是:id
的value當作外面id:
的value
聽起來很像繞口令,讓我們一步一步拆開來看。
params本身是Hash的資料型態,也就是上面有敘述過的一大串資料:
{"utf8"=>"✓", "authenticity_token"=>"0OHbZ7WkDs8NsrNHK2s7Dd9BxkITn/qegeFtUcMmE5ANKKiaxmRCOiPuChEAoKh4ho/taDYBB7GvIhTG0a1IHw==", "candidate"=>{"name"=>"Louis", "party"=>"none", "age"=>"20", "policy"=>"Rails is Good"}, "commit"=>"Create Candidate", "controller"=>"candidates", "action"=>"create"}
上面有講過個例子,若我要拿到Louis,我需要寫params['candidate']['name']
才能拿到對吧?
params['candidate']['name']
↓ ↓
({ id: params[:id]})
假設 params = { id: 5, email: 'kk@5xruby.tw', name: 'Louis' }
find_by(id: params[:id], email: params[:email], name: params[:name])
find_by( 5 , kk@5xruby.tw , Louis )
這樣可以找到在候選人表格裡「id 是 5,而且 email 是 kk@5xruby.tw,而且 name 是 Louis」的候選人
這樣對應著看,應該有比較容易理解吧!!
但還是會出現錯誤(笑
記得也要在views建立 show.html.erb
<% if @candidate %>
<h1><%= @candidate.name %></h1>
<ul>
<li>黨派: <%= @candidate.party%> </li>
<li>年紀: <%= @candidate.age%> </li>
<li>政見: <%= @candidate.policy%> </li>
</ul>
<% else %>
<h1>沒有這個人</h1>
<% end %>
就終於完成了簡易CRUD中的C跟R...
參考資料:
“The difference in winning and losing is most often…not quitting.”
— Walt Disney, Producer
本文同步發佈於: https://louiswuyj.tw/